package ltu.thole;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class WiFiScanner extends Activity implements OnClickListener {
	
	WifiManager wifi;
	BroadcastReceiver receiver;
	private ArrayList<Device> deviceList = new ArrayList<Device>();
	private ArrayList<DeviceProximity> proximityList = new ArrayList<DeviceProximity>();
	private WiFiRoughlyPosition currentPosition = null;
	private static final int REQUEST_CODE = 10;
	private boolean waitForData = false;
	private boolean continuousScan = true;
	private static int deviation = 14;
	
	private TextView textStatus;
	private Button buttonScan;
	private Button buttonScanSetting;
	private Button buttonAdd;
	private Button buttonList;
	
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.wifi);

		textStatus = (TextView) findViewById(R.id.textStatus);
		buttonScan = (Button) findViewById(R.id.buttonScan);
		buttonScan.setOnClickListener(this);
		buttonScanSetting = (Button) findViewById(R.id.buttonScanSetting);
		buttonScanSetting.setOnClickListener(this);
		buttonAdd = (Button) findViewById(R.id.buttonAdd);
		buttonAdd.setOnClickListener(this);
		buttonList = (Button) findViewById(R.id.buttonList);
		buttonList.setOnClickListener(this);
		
		// Setup WiFi
		wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);

		// Get WiFi status
		WifiInfo info = wifi.getConnectionInfo();
		textStatus.append("\n\nWiFi Status: " + info.toString());

		// List available networks
		List<WifiConfiguration> configs = wifi.getConfiguredNetworks();
		for (WifiConfiguration config : configs) {
			textStatus.append("\n\n" + config.toString());
		}
		
		// Register Broadcast Receiver
		if (receiver == null) {
			receiver = new WiFiScanReceiver(this);
		}
		
	}
	
	@Override
	public void onDestroy() {
		Toast.makeText(this, "onDestroy()", Toast.LENGTH_SHORT).show();
		unregisterReceiver(receiver);
	}
	
	public void scanReceived(List<ScanResult> results) {
		if (!continuousScan) {
			unregisterReceiver(receiver);
		}
		currentPosition = new WiFiRoughlyPosition(results);
		String resultText = "";
		for (ScanResult result : results) {
			resultText += ("\n\nSSID: " + result.SSID + "\nMAC-address: " + result.BSSID + "\nLevel: " + result.level);
		}
		textStatus.setText(resultText);
		
		checkForDeviceInProximity(currentPosition);
		//checkDeviceProximity(results);
		
		if (waitForData && (currentPosition != null)) {
			addDevice();
		}
		
	}
	
	private void checkDeviceProximity(List<ScanResult> scanResult) {
		
		proximityList = new ArrayList<DeviceProximity>();
		
		for (int i = 0; i < deviceList.size(); i++) {

			proximityList.add(new DeviceProximity(deviceList.get(i), deviceList.get(i).compareTo(scanResult)));
			
		}
		
		if (proximityList.size() > 0) {
			String text = "";
			int prox;
			for (int i = 0; i < proximityList.size(); i++) {
				prox = (int)(proximityList.get(i).getProximity()*100);
				text += prox + "% " + proximityList.get(i).getDevice().getName() + "\n";
			}
			Toast.makeText(this, (text), Toast.LENGTH_LONG).show();
		}
		
	}
	
	private void checkForDeviceInProximity(WiFiRoughlyPosition position) {
		
		int matchingMacAddresses;
		int matchingStrengths;
		
		double ratioMacAddresses;
		double ratioStrength;
		int currentStrength;
		int deviceStrength;
		
		proximityList = new ArrayList<DeviceProximity>();
		
		// Go through all the devices in the deviceList.
		for (int i = 0; i < deviceList.size(); i++) {

			ratioStrength = 0;
			matchingMacAddresses = 0;
			matchingStrengths = 0;
			// Go through all the current scan results.
			for (int j = 0; j < position.size(); j++) {
				
				// Go through all the scan results for this device.
				for (int k = 0; k < deviceList.get(i).getPosition().size(); k++) {
					// If a matching MAC-address is found.
					if (position.getResults().get(j).BSSID.contains(deviceList.get(i).getPosition().getResults().get(k).BSSID)) {
						//Matching MAC-addresses.
						matchingMacAddresses++;
						currentStrength = position.getResults().get(j).level;
						deviceStrength = deviceList.get(i).getPosition().getResults().get(k).level;
						// Check if the signal strength matches.
						if ((currentStrength >= (deviceStrength - deviation)) && (currentStrength <= (deviceStrength + deviation))) {
							// Signal strength is within margin of error.
							matchingStrengths++;
							if (currentStrength > deviceStrength) {
								ratioStrength += (Double.parseDouble(""+(currentStrength*-1))/Double.parseDouble(""+(deviceStrength*-1)));
								//Toast.makeText(this, ("ratioStrength: " + ratioStrength + "(" + currentStrength + ", " + deviceStrength + ")"), Toast.LENGTH_LONG).show();
							}
						}
					}
				}
			}
			
			ratioMacAddresses = (Double.parseDouble(""+(matchingMacAddresses)/Double.parseDouble(""+(deviceList.get(i).getPosition().getResults().size()))));
			ratioStrength = (ratioStrength/Double.parseDouble(""+(matchingMacAddresses)));
			//Toast.makeText(this, ("ratioMacAddresses: " + ratioMacAddresses + "\nratioStrength: " + ratioStrength), Toast.LENGTH_LONG).show();
			//Toast.makeText(this, ("Ratio: " + ((ratioStrength*ratioMacAddresses)*100) + "%"), Toast.LENGTH_LONG).show();
			//Toast.makeText(this, ("matchingMacAddresses: " + matchingMacAddresses + "\nmatchingStrengths: " + matchingStrengths), Toast.LENGTH_LONG).show();
			proximityList.add(new DeviceProximity(deviceList.get(i), ratioStrength));
		}
		
		
		if (proximityList.size() > 0) {
			String text = "";
			int prox;
			for (int i = 0; i < proximityList.size(); i++) {
				prox = (int)(proximityList.get(i).getProximity()*100);
				text += prox + "% " + proximityList.get(i).getDevice().getName() + "\n";
			}
			Toast.makeText(this, (text), Toast.LENGTH_LONG).show();
		}

	}
	
	/*
	@Override
	public void onStop() {
		unregisterReceiver(receiver);
	}
	*/

	@Override
	public void onClick(View view) {

		if (view.getId() == R.id.buttonScan) {
			registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
			wifi.startScan();
		} else if (view.getId() == R.id.buttonScanSetting) {
			if (continuousScan) {
				continuousScan = false;
				unregisterReceiver(receiver);
				buttonScanSetting.setText("Auto: off");
			} else {
				continuousScan = true;
				registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
				buttonScanSetting.setText("Auto: on");
			}
		} else if (view.getId() == R.id.buttonAdd) {
			waitForData = true;
			registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
			wifi.startScan();
			
			/*
			if (currentPosition == null) {
				waitForData = true;
				registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
				wifi.startScan();
			} else {
				addDevice();
			}
			*/
		} else if (view.getId() == R.id.buttonList) {
			Intent listDevices = new Intent();
			listDevices.setClass(this, DeviceList.class);
			startActivity(listDevices);
		}
		
	}
	
	private void addDevice() {
		waitForData = false;
		//unregisterReceiver(receiver);
		Intent addDevice = new Intent(this, AddDevice.class);
		startActivityForResult(addDevice, REQUEST_CODE);
	}
	
    @Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

		if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {

			String name = data.getExtras().getString("name");
			String address = data.getExtras().getString("address");
			String port = data.getExtras().getString("port");
			int portNumber = Integer.parseInt(port);
			
			Device dev = new Device(name, address, portNumber, currentPosition);
			deviceList.add(dev);

			String msg = ("Device Successfully Added\nName: " + dev.getName() + "\nIP-address: " + dev.getAddress() + "\nPort: " + dev.getPort());
			Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
		}

	}


}